<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>

  <script>
    const obj = { name: '孙悟空', age: 18 };

    function fn(...args) {
      args.forEach((item) => console.log(item))
      console.log('this', this);
    }

    const newFn = fn.bind(obj, 1, 2, 3);
    newFn();

    /**
     * 分析关键点是什么
     * 1. 这个 mybind 一定是函数调用的方法而不是对象的方法
     * 2. 调用它的函数，所有的逻辑代码正常执行，只是改变了 this 的指向
     * 3. 这个 mybind 一定会返回一个新的函数
     *
     * 问题：如何获取到调用 mybind 的方法？这不是通过参数传递过来的，而是 xx.myBind()，
     * 答案：通过 this 关键字，来获取调用 xx 的信息，谁调用，this 就指向谁
     */
    Function.prototype.mybind = function (context) {
      console.log('this', this); // 当前调用 mybind 的函数
      if (typeof this !== "function") {
        throw new Error('myBind must be called on a function');
      }
      // 获取原函数
      const fn = this;
      console.log('--arguments', arguments); // 包含 context 和预绑定的参数
      // 获取从第二个参数开始的所有参数
      const args = Array.prototype.slice.call(arguments, 1);
      // 返回一个新函数
      return function () {
        console.log('++arguments', arguments); // 新函数调用时传入的参数，将通过 apply 传递给原函数
        // 获取新函数被调用时传入的参数
        const newArgs = Array.prototype.slice.call(arguments);
        // 将原函数绑定到指定上下文并传入所有参数后返回结果
        return fn.apply(context, args.concat(newArgs));
      };
    };

    fn.mybind(obj, 1, 2, 3).mybind(4,5)(6,7)
  </script>
</body>
</html>
